﻿using System.Linq;

using System.Collections.Generic;
using CooliteExample.Model;
using CooliteExamples.Code.DTO;
using CooliteExamples.Core.Exceptions;

namespace CooliteExamples.Code.DAL
{
    public static class BookDal
    {
        public static List<Book> GetBooks()
        {
            using (BookManagerEntities context = new BookManagerEntities())
            {
                return (from b in context.BookSet.Include("Category").Include("Authors").ToList()
                        select new Book
                                   {
                                       BookId = b.BookId,
                                       Title = b.Title,
                                       ISBN = b.ISBN,
                                       Authors = b.Authors.Select(a => new Author(a)).ToList(),
                                       Category = new Category(b.Category)
                                   }).ToList();
            }
        }

        public static List<Book> GetBooksForAuthor(int authorId)
        {
            using (BookManagerEntities context = new BookManagerEntities())
            {
                var author = context.AuthorSet.Include("Books").FirstOrDefault(a => a.AuthorId == authorId);
                return author.Books.Select(b => new Book(b)).ToList();
            }
        }

        public static int SaveBook(Book book)
        {
            using (BookManagerEntities context = new BookManagerEntities())
            {
                mBook bookToSave = new mBook();
                if (book.BookId > 0)
                    bookToSave = context.BookSet.Include("Authors").FirstOrDefault(b => b.BookId == book.BookId);
                else
                    context.AddToBookSet(bookToSave);

                // update simple properties
                bookToSave.Category = context.CategorySet.FirstOrDefault(c => c.CategoryId == book.CategoryId);
                bookToSave.ISBN = book.ISBN;
                bookToSave.Title = book.Title;

                // save authors
                var currentAuthorIdList = bookToSave.Authors.Select(a => a.AuthorId).ToList();
                var authorIdList = book.Authors.Select(a => a.AuthorId);

                // determine new authors
                authorIdList.Where(a => !currentAuthorIdList.Contains(a)).Select(a =>
                                                                                     {
                                                                                         var newAuthor = context.AuthorSet.FirstOrDefault(a1 => a1.AuthorId == a);
                                                                                         bookToSave.Authors.Add(newAuthor);
                                                                                         return true;       // this is need for Select
                                                                                     }).ToList();

                // determine removed authors
                bookToSave.Authors.Where(a => !authorIdList.Contains(a.AuthorId)).Select(a => bookToSave.Authors.Remove(a)).ToList();

                context.SaveChanges(true);
                return bookToSave.BookId;
            }
        }

        public static void DeleteBook(Book book)
        {
            using (BookManagerEntities context = new BookManagerEntities())
            {
                mBook theBook = context.BookSet.FirstOrDefault(b => b.BookId == book.BookId);
                if (theBook == null)
                    throw new BookManagerOperationException("Could not find selected book - please choose another");

                context.DeleteObject(theBook);
                context.SaveChanges();
            }
        }
    }
}
